/**
 * 
 */
package com.bsc.protracted.daos;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

/**
 * @author peike.ma
 * @see data source base method
 *
 */
//@SuppressWarnings("unchecked")
public abstract class DaosPublic<T> extends HibernateDaoSupport implements BaseDao<T> {

    private static final Logger log = LoggerFactory.getLogger(DaosPublic.class);
    
//    @Autowired
//    public MemcachedClient memcachedClient;

    /**
     * session factory
     *
     * @param sessionfactory
     */
    @Resource(name = "sessionFactory")
    public void setSuperSessionFactory(SessionFactory sessionfactory) {
        super.setSessionFactory(sessionfactory);
    }

    //delete
    public void delete(Object obj) {
        super.getHibernateTemplate().delete(obj);
    }

    //get obj list
    public List<T> get(final Class obj) {
        return get(obj, true);
    }

    //get obj list order
    public List<T> get(final Class obj, final boolean order) {
        List list = null;

        list = super.getHibernateTemplate().execute(new HibernateCallback<List>() {

            public List doInHibernate(Session session) throws HibernateException, SQLException {
                Order ord = Order.asc("id");
                if (order) {
                    ord = Order.desc("id");
                }
                return session.createCriteria(obj).addOrder(ord).list();
            }
        });
        return list;
    }

    //get Object for id
    public Object get(Class obj, Serializable id) {
        Object objs = null;
        objs = super.getHibernateTemplate().get(obj, id);
        return objs;
    }

    //get obj list where key equals value or key onEquals value
    public List get(final Class obj, final String key, final Object value, final boolean isEq) {
        return get(obj, key, value, true, isEq);
    }

    public List get(final Class obj, final String key, final Object value, final boolean order, final boolean isEq) {
        return (List) super.getHibernateTemplate().execute(new HibernateCallback<List>() {

            public List doInHibernate(Session session) throws HibernateException, SQLException {
                Order ord = Order.asc("id");
                if (order) {
                    ord = Order.desc("id");
                }
                if (isEq) {
                    return (List) session.createCriteria(obj).add(Restrictions.eq(key, value)).addOrder(ord).list();
                } else {
                    return (List) session.createCriteria(obj).add(Restrictions.ne(key, value)).addOrder(ord).list();
                }
            }
        });
    }

    //get obj list where map is equals
    public List get(final Class obj, final Map map, final boolean order) {
        return (List) super.getHibernateTemplate().execute(new HibernateCallback<List>() {

            public List doInHibernate(Session session) throws HibernateException, SQLException {
                Order ord = Order.asc("id");
                if (order) {
                    ord = Order.desc("id");
                }
                return (List) session.createCriteria(obj).add(Restrictions.allEq(map)).addOrder(ord).list();
            }
        });
    }

    //get T for first between first+max
    public T get(final Class obj, final int first, final int max) {
        return get(obj, first, max, true);
    }

    public T get(final Class obj, final int first, final int max, final boolean order) {
        return (T) super.getHibernateTemplate().execute(new HibernateCallback<T>() {

            public T doInHibernate(Session sn) throws HibernateException, SQLException {
                Order ord = Order.asc("id");
                if (order) {
                    ord = Order.desc("id");
                }
                return (T) sn.createCriteria(obj).setFirstResult(first).setMaxResults(max).addOrder(ord).list();
            }
        });
    }

    public T get(final Class obj, final String key, final Object value, final int first, final int max, final boolean order) {
        return (T) super.getHibernateTemplate().execute(new HibernateCallback<T>() {

            public T doInHibernate(Session sn) throws HibernateException, SQLException {
                Order ord = Order.asc("id");
                if (order) {
                    ord = Order.desc("id");
                }
                return (T) sn.createCriteria(obj).add(Restrictions.ne(key, value)).setFirstResult(first).setMaxResults(max).addOrder(ord).list();
            }
        });
    }

    //get obj list total
    public int getTotalCount(final Class obj) {
        return super.getHibernateTemplate().execute(new HibernateCallback<Integer>() {

            public Integer doInHibernate(Session sn) throws HibernateException, SQLException {
                return ((Integer) sn.createCriteria(obj).setProjection(Projections.rowCount()).uniqueResult()).intValue();
            }
        });
    }

    //save obj
    public int save(Object obj) {
        int id = (Integer) super.getHibernateTemplate().save(obj);
        super.getHibernateTemplate().flush();
        return id;
    }

    //updata obj
    public void updata(Object obj) {
        super.getHibernateTemplate().update(obj);
        super.getHibernateTemplate().flush();
    }
            //get obj list by hql
    public List get(final String hql) {
        return super.getHibernateTemplate().find(hql);
    }
 // all object save
    public int save(final List list) {
        return super.getHibernateTemplate().execute(new HibernateCallback<Integer>() {
            public Integer doInHibernate(Session sn) throws HibernateException, SQLException {
                int lengeh = -1;
                try{
                    lengeh =list.size();
                    for(int i = 0; i< lengeh;i++ ){
                        sn.saveOrUpdate(list.get(i));
                         if(i%50 == 0){     
                            sn.flush();     
                            sn.clear();     
                        } 
                    }
                    sn.flush();
                }catch(Exception e){
                    e.printStackTrace();
                }
                return lengeh;
            }
        });    
    } 
}
